package com.sptci.rwt;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import java.util.ArrayList;
import java.util.List;

import com.sptci.util.CloseJDBCResources;

/**
 * A utility class to execute SQL statements (single or batch).
 *
 * <p>&copy; Copyright 2007 Sans Pareil Technologies, Inc.</p>
 * @author Rakesh Vidyadharan 2007-10-01
 * @version $Id: BatchQueryExecutor.java 2 2007-10-19 21:06:36Z rakesh.vidyadharan $
 */
public class BatchQueryExecutor extends AbstractQueryExecutor
{
  /**
   * Create a new instance using the specified manager to fetch connections.
   *
   * @param manager The connection manager to use.
   */
  public BatchQueryExecutor( final ConnectionManager manager )
  {
    super( manager );
  }

  /**
   * Execute the specified statement(s) and return all the {@link
   * java.sql.ResultSet} and {@link java.sql.Statement#getUpdateCount} 
   * values that result from executing the statement(s).
   *
   * @see #createStatement
   * @see #processResultSet
   * @see #processUpdateCount
   * @param sql The statement(s) to be executed.
   * @param maxRows The maximum number of rows to fetch for any statement.
   * @return A collection of {@link Rows} objects that represents all
   *   the {@link java.sql.ResultSet} and {@link
   *   java.sql.Statement#getUpdateCount}s generated by executing the
   *   statement(s).
   * @throws SQLException If errors are encountered while executing the
   *   statement(s).
   */
  public List<Rows> execute( final String sql, final int... maxRows )
    throws SQLException
  {
    Connection connection = null;
    CallableStatement statement = null;
    List<Rows> collection = new ArrayList<Rows>();
    
    try
    {
      connection = manager.open();
      statement = createStatement( sql, connection );
      if ( ( maxRows != null ) && ( maxRows.length > 0 ) )
      {
        statement.setMaxRows( maxRows[0] );
      }

      boolean status = statement.execute();

      if ( status )
      {
        collection.add( processResultSet( statement, 0, Integer.MAX_VALUE ) );
      }
      else
      {
        collection.add( processUpdateCount( statement ) );
      }

      boolean hasMore = false;
      int updateCount = -1;
      while ( ( hasMore = statement.getMoreResults() ) ||
        ( ( updateCount = statement.getUpdateCount() ) != -1 ) )
      {
        collection.add( ( ( hasMore ) ? 
            processResultSet( statement, 0, Integer.MAX_VALUE ) :
            processUpdateCount( statement ) ) );

        hasMore = false;
        updateCount = -1;
      }
    }
    finally
    {
      CloseJDBCResources.close( statement );
      CloseJDBCResources.close( connection );
    }

    return collection;
  }
}
